package com.ce.framework.datamaintain.implement;

import java.io.File;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.poi2.hssf.usermodel.HSSFWorkbook;
import org.apache.struts2.ServletActionContext;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.ce.framework.constants.WebConstants;
import com.ce.framework.datamaintain.dao.IBaseDao;
import com.ce.framework.datamaintain.logic.DivideInfo;
import com.ce.framework.datamaintain.logic.ISQLMapper;
import com.ce.framework.datamaintain.logic.ISearchCondition;
import com.ce.framework.datamaintain.logic.ISearchInfo;
import com.ce.framework.datamaintain.logic.SQLSearchCondition;
import com.ce.framework.exception.AppException;
import com.ce.framework.exception.DaoException;
import com.ce.framework.util.BeanAccessUtil;
import com.ce.framework.util.LogUtil;
import com.ce.framework.util.StringUtil;
import com.ce.util.DbUtil;

/**
 * 嫦娥软件有限公司 版权所有 2013
 * 创建人： andy
 * 创建时间： Aug 24, 2010 10:12:29 AM
 * 功能描述：基类DAO的实现类
 * ==================================
 * 修改历史
 * 修改人        修改时间      修改位置（函数名）
 *
 * ==================================
 */
public class BaseDao extends HibernateDaoSupport implements IBaseDao {

	public void addPo(Object po) throws AppException, DataAccessException {
		// TODO Auto-generated method stub
		if(po!=null)
			this.getHibernateTemplate().save(po);
	}

	public void deletePos(List<?> delList) throws AppException,
			DataAccessException {
		if(delList!=null&&delList.size()>0)
			this.getHibernateTemplate().deleteAll(delList);
	}

	public void deleteSearchHQL(String hql) throws AppException,
			DataAccessException {
		if(StringUtil.isNotBlank(hql)){
			List<?> list = this.getHibernateTemplate().find(hql);
			this.getHibernateTemplate().deleteAll(list);
		}
	}



	public Object getPo(String poClassName, String selectedId)
			throws AppException, DataAccessException {
		// TODO Auto-generated method stub
		return this.getHibernateTemplate().get(poClassName, selectedId);
	}


	public int deleteLogic(String  poClassName, String[] ids, String delField,String childPoName)
			throws AppException {
		// TODO Auto-generated method stub
		Class<?> clazz = null;
		try {
			clazz = Class.forName(poClassName);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		if(clazz==null){
			String errorMsg="没有找到"+poClassName+"类，请检查。";
			throw new AppException(errorMsg);
		}
		int deleteItemCount=0;
		HibernateTemplate ht=this.getHibernateTemplate();
		if(StringUtil.isBlank(delField))
			delField = WebConstants.DEFAULT_DELETE_FIELD;
		for(int i=0; i<ids.length; i++){
			//Long lId=Long.valueOf(ids[i]);
			Object obj=ht.load(clazz,ids[i].trim());
			if(obj!=null){
				try {
					Class<?> cla = BeanAccessUtil.getProptType(obj, delField);
					if(String.class.equals(cla))
						BeanAccessUtil.copyProperty(obj, delField, "1");
					else if(Integer.class.equals(cla))
						BeanAccessUtil.copyProperty(obj, delField, new Integer(1));
					else if(Long.class.equals(cla))
						BeanAccessUtil.copyProperty(obj, delField, new Long(1));
					else if(int.class.equals(cla))
						BeanAccessUtil.copyProperty(obj, delField, 1);
					else if(long.class.equals(cla))
						BeanAccessUtil.copyProperty(obj, delField, 1);
					ht.update(obj);
					deleteItemCount++;
					try{//删除对应的子表数据（物理删除）
						if(StringUtil.isNotBlank(childPoName)){
							this.deleteSearchHQL("from "+childPoName+" po where po.vcMid='"+ids[i]+"'");	
						}
					}catch(Exception e){
					   throw new AppException("主表主键名称不是vcMid，子表未删除！",e);	
					}
					continue;
				} catch (Exception e) {
					throw new AppException("主表删除出现错误。"+e.getMessage(),e);
				}
			}
		}
		
		return deleteItemCount;
	}



	public void updatePo(Object po) throws AppException, DataAccessException {
		// TODO Auto-generated method stub
		if(po!=null)
			this.getHibernateTemplate().saveOrUpdate(po);
	}

	public void updatePos(Collection<?> pos) throws AppException,
			DataAccessException {
		// TODO Auto-generated method stub
		if(pos!=null&&pos.size()>0)
			this.getHibernateTemplate().saveOrUpdateAll(pos);
	}

	
	public List<Object> search(ISearchInfo searchInfo) throws AppException, DataAccessException {
		ISearchCondition searchCndt = searchInfo.getSearchCondition();
		ISQLMapper mapper = ((SQLSearchCondition)searchCndt).getSQLMapper();
		List<Object> list = queryData(searchInfo, mapper);
        return list;
	}

	public List<Object> search(ISearchCondition searchCndt) throws AppException, DataAccessException {
		ISQLMapper mapper = ((SQLSearchCondition)searchCndt).getSQLMapper();
		List<Object> list = queryData(searchCndt, mapper);
		return list;
	}

	public void getDivideResultInfo(ISearchInfo searchInfo)
				throws AppException,DataAccessException{
		//得到SQL语句。
		SQLSearchCondition searchCndt = (SQLSearchCondition) searchInfo.getSearchCondition();
		int recordAmount=this.getRecordCount(searchCndt);
		DivideInfo divideInfo=searchInfo.getDivideInfo();
		divideInfo.setRowAmount(recordAmount);
	}

	public int getRecordCount(SQLSearchCondition condition) throws AppException, DataAccessException {

		String sql = condition.getSearchCntSql();
//		int recordAmount=this.getRecordCount(SQL);
		//对SQL语句进行解析，找到其中${变量名}中带的变量值，将变量解析出来，从SearchCondition中将变量值取出
		Pattern pat = Pattern.compile("\\$\\{([^\\}]+)\\}");
		Matcher mat = pat.matcher(sql);
		List<Object> paraml = new ArrayList<Object>();
		int index = 0;
		while(mat.find()){
			String pa = mat.group(1);
			Object value = null;
			try {
				value = PropertyUtils.getSimpleProperty(condition, pa);
			} catch (Exception e) {
				e.printStackTrace();
			}
			paraml.add(index++,value);
		}
		Object [] params = new Object[index];
		for(int i=0;i<index;i++){
			params[i] = paraml.get(i);
		}
		sql = sql.replaceAll("'?\\$\\{([^\\}]+)\\}'?", "?");
		int recordAmount = DbUtil.getFirstIntSqlQuery(sql,params);
		return recordAmount;
	}

	/**
	 * 开发人： andy
	 * 开发时间： 2013-7-22 下午05:03:46
	 * 功能描述：用于通过sql语句获取对应po对象的方法，私有类，只为通用查询时获取分页数据时使用
	 * 方法的参数和返回值
	 * @param sql  带参数的sql语句
	 * @param searchCndt   searchConditon
	 * @param mapper
	 * @return
	 * List<Object> 
	 * ==================================
	 * 修改历史
	 * 修改人        修改时间      修改原因及内容
	 *
	 * ==================================
	 * @throws AppException 
	 */
	@SuppressWarnings("unchecked")
	public List<Object> queryData(ISearchInfo searchInfo, ISQLMapper mapper) throws AppException {
		ISearchCondition searchCndt = searchInfo.getSearchCondition();
		DivideInfo divideInfo = searchInfo.getDivideInfo();
		String sql = null;
		try {
			sql = searchCndt.getSearchSql();
		} catch (AppException e1) {
			LogUtil.logError(e1);
		}
		if(sql==null){
			return null;
		}
		//对SQL语句进行解析，找到其中${变量名}中带的变量值，将变量解析出来，从SearchCondition中将变量值取出
		Pattern pat = Pattern.compile("\\$\\{([^\\}]+)\\}");
		Matcher mat = pat.matcher(sql);
		List<Object> paraml = new ArrayList<Object>();
		int index = 0;
		while(mat.find()){
			String pa = mat.group(1);
			Object value = null;
			try {
				value = PropertyUtils.getSimpleProperty(searchCndt, pa);
			} catch (Exception e) {
				e.printStackTrace();
			}
			paraml.add(index++,value);
		}
		Object [] params = new Object[index+2];
		for(int i=0;i<index;i++){
			params[i] = paraml.get(i);
		}
		params[index] = divideInfo.getEndRowNo();
		params[index+1] = divideInfo.getBegRowNo();
		sql = sql.replaceAll("'?\\$\\{([^\\}]+)\\}'?", "?");
		mat = orderByPat.matcher(sql);
		if(mat.find()){//将order by 子句放入request中，供<h:table/>标签解析出排序的汉字
			try {
				ServletActionContext.getRequest().setAttribute("orderBy", mat.group(1));
			} catch (Throwable e) {
				e.printStackTrace();
			}
		}
        String newSql = "select * from (select sql_$t.*,rownum sql_$r from (" + sql + ") sql_$t where rownum<=?" + 
        		") where sql_$r>?";
        newSql = searchCndt.getDividePageSql(sql, -1, -1);
        newSql = newSql.replaceAll("rownum\\<\\=\\d+", "rownum<=?").replaceAll("sql\\_\\$r\\>\\d+", "sql_$r>?");
		List list = DbUtil.executeSqlQuery(newSql, mapper,params);
		return list;
	}
	private Pattern orderByPat = Pattern.compile(".*order\\s+by\\s+(.+)");

	@SuppressWarnings("unchecked")
	public List<Object> queryData(ISearchCondition searchCndt, ISQLMapper mapper) throws AppException {
		String sql = null;
		try {
			sql = searchCndt.getSearchSql();
		} catch (AppException e1) {
			LogUtil.logError(e1);
		}
		if(sql==null){
			return null;
		}
		//对SQL语句进行解析，找到其中${变量名}中带的变量值，将变量解析出来，从SearchCondition中将变量值取出
		Pattern pat = Pattern.compile("\\$\\{([^\\}]+)\\}");
		Matcher mat = pat.matcher(sql);
		List<Object> paraml = new ArrayList<Object>();
		int index = 0;
		while(mat.find()){
			String pa = mat.group(1);
			Object value = null;
			try {
				value = PropertyUtils.getSimpleProperty(searchCndt, pa);
			} catch (Exception e) {
				e.printStackTrace();
			}
			paraml.add(index++,value);
		}
		Object [] params = new Object[index];
		for(int i=0;i<index;i++){
			params[i] = paraml.get(i);
		}
		sql = sql.replaceAll("'?\\$\\{([^\\}]+)\\}'?", "?");
		mat = orderByPat.matcher(sql);
		if(mat.find()){//将order by 子句放入request中，供<h:table/>标签解析出排序的汉字
			try {
				ServletActionContext.getRequest().setAttribute("orderBy", mat.group(1));
			} catch (Throwable e) {
				e.printStackTrace();
			}
		}
		List list = DbUtil.executeSqlQuery(sql, mapper,params);
		return list;
	}
	
	public void addPos(Collection<?> pos) throws AppException, DataAccessException {
		// TODO Auto-generated method stub
		if(pos!=null&&pos.size()>0)
		  this.getHibernateTemplate().saveOrUpdateAll(pos);
	}

	public List<?> findByHql(final String hql) throws DaoException {
		// System.out.println("@@@:"+hql);
		try {
			return this.getHibernateTemplate().find(hql);
		} catch (RuntimeException re) {
			throw new DaoException(re.getMessage(), re);
		}
	}

	public List<?> findByHql(final String hql,Object[] params) throws DaoException {
		// System.out.println("@@@:"+hql);
		try {
			return this.getHibernateTemplate().find(hql,params);
		} catch (RuntimeException re) {
			throw new DaoException(re.getMessage(), re);
		}
	}
	
	public List<?> findByHql(final String hql,final int begin,final int count) throws DaoException {
		// System.out.println("@@@:"+hql);
		try {
			List<?> resultData=null;
			resultData = this.getHibernateTemplate().executeFind(new HibernateCallback(){
				
					public Object doInHibernate(Session session) throws HibernateException, SQLException {
						Query query=session.createQuery(hql);
						query.setFirstResult(begin);
	                    query.setMaxResults(count);
	                    List<?> datas = query.list();
						return datas;
					}
				}
			);
			return resultData;
		} catch (RuntimeException re) {
			throw new DaoException(re.getMessage(), re);
		}
	}

	public List<?> findByCriteria(DetachedCriteria detachedCriteria) {

		return getHibernateTemplate().findByCriteria(detachedCriteria);

	}

	public int getCountByCondition(DetachedCriteria detachedCriteria) {
		Criteria criteria = detachedCriteria
				.getExecutableCriteria(getSession());
		int count = ((Integer) criteria.setProjection(Projections.rowCount())
				.uniqueResult()).intValue();
		return count;
	}
	
	public void delete(Object po){
		this.getHibernateTemplate().delete(po);
	}

}
